package com.sunriz.motordrive.utils;

import com.sunriz.motordrive.server.common.impl.BaseSerialImpl;
import jssc.SerialPort;
import jssc.SerialPortException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * ClassName: TxMsg
 * Package: com.sunriz.modbus
 * Description:
 *
 * @Author BuTang
 * @Create 2024/1/19 10:31
 * @Version 1.0
 */
@Slf4j
public class TxMsg {

    /**
     * 发送modbus 请求 03报文
     * @param bytes
     * @throws SerialPortException
     */
    public static void txRequest16(byte[] bytes) throws SerialPortException {
//        byte[] bytes = {1, 3, 8, 0, 0, 0, 1};
        String s = Crc.Crc16(bytes);
        String substring = s.substring(0, 2);
        String substring1 = s.substring(2);
//        byte[] substringBytes = substring.getBytes();

        byte[] newBytes  = new byte[(bytes.length + 2)];
        System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
        newBytes[newBytes.length - 2] = (byte) Integer.parseInt(substring, 16);
        newBytes[newBytes.length - 1] = (byte) Integer.parseInt(substring1, 16);
        BaseSerialImpl.serialPort.writeBytes(newBytes);
    };
    public static void txBack16(SerialPort serialPort, Integer slaveId, Integer model, Integer addrOrNum, List<Integer> date) {
        List<Integer> dataList = new ArrayList();

        //将数据转换为4位的数值，然后进行切割
        for (int i = 0; i < date.size(); i++) {
            Integer i1 = Integer.parseInt(String.valueOf(date.get(i)));
            // 十六进制数
            String s = Integer.toHexString(i1);
            boolean flag = true;

            while (flag) {
                if (s.length() < 4) {
                    s = 0 + s;
                } else {
                    flag = false;
                }
            }
            String firstTwoDigits = s.substring(0, 2);
            String secondTwoDigits = s.substring(2, 4);

            dataList.add(Integer.parseInt(firstTwoDigits, 16));
            dataList.add(Integer.parseInt(secondTwoDigits, 16));
        }

        //把slaveId，model，addr，num 放入集合，计算crc
        List<String> dates = new ArrayList<>();
        dates.add(String.format("%02X", slaveId));
        dates.add(String.format("%02X", model));

        //确定发送报文时第三字节是寄存器数量or起始地址
        switch (model) {
            case 06:
            case 16: {
                String add = String.format("%04X", addrOrNum);
                String adda = add.substring(0, 2);
                String addb = add.substring(2, 4);
                dates.add(adda);
                dates.add(addb);
                break;
            }
            case 03:
            case 04: {
                int i = addrOrNum * 2;
                String num1 = String.format("%02X", i);
                dates.add(num1);
                break;
            }
            default:
                log.error("发送报文时，解析区分0304/0616 出错，此时的数据:slaveId:{},model:{},addrOrNum:{},date:{}", slaveId, model, addrOrNum, date.toString());
        }

        for (int i = 0; i < dataList.size(); i++) {

            String value = String.format("%02X", dataList.get(i));
            dates.add(value);
        }

        byte[] crcByte = new byte[0];
        for (String date2 : dates) {
            int date10 = Integer.parseInt(date2, 16);
            // 扩展crc数组长度
            crcByte = Arrays.copyOf(crcByte, crcByte.length + 1);
            // 将date10添加到crc数组末尾
            crcByte[crcByte.length - 1] = (byte) date10;
        }
        String crc = Crc.Crc16(crcByte);

//        System.out.println("CRC校验值: " + crc);
        String firstTwoDigits = crc.substring(0, 2);
        String secondTwoDigits = crc.substring(2, 4);
        dates.add(firstTwoDigits);
        dates.add(secondTwoDigits);

        StringBuilder sb = new StringBuilder();
        for (String byteStr : dates) {
            sb.append(byteStr).append(" ");
        }
        String message = sb.toString().trim();
//        System.out.println("回复TX报文: " + message);
        String[] byteStrings = message.split(" ");
        // 创建一个与 byteStrings 长度相同的 byte 数组
        byte[] byteArray = new byte[byteStrings.length];

        // 将每个字符串解析为十六进制并放入 byte 数组
        for (int i = 0; i < byteStrings.length; i++) {
            byteArray[i] = (byte) Integer.parseInt(byteStrings[i], 16);
        }

        try {
            // 发送Modbus报文
            serialPort.writeBytes(byteArray);
        } catch (SerialPortException e) {
            throw new RuntimeException(e);
        }
    }

    public static void txBack32(SerialPort serialPort, Integer slaveId, Integer model, Integer addrOrNum, List<Integer> date) {
        List<Integer> dataList = new ArrayList();

        //将数据转换为8位的数值，然后进行切割
        for (int i = 0; i < date.size(); i++) {
            Integer i1 = Integer.parseInt(String.valueOf(date.get(i)));
            // 十六进制数
            String s = Integer.toHexString(i1);
            boolean flag = true;

            while (flag) {
                if (s.length() < 8) {
                    s = 0 + s;
                } else {
                    flag = false;
                }
            }
            String TwoDigits1 = s.substring(0, 2);
            String TwoDigits2 = s.substring(2, 4);
            String TwoDigits3 = s.substring(4, 6);
            String TwoDigits4 = s.substring(6, 8);

            dataList.add(Integer.parseInt(TwoDigits1, 16));
            dataList.add(Integer.parseInt(TwoDigits2, 16));
            dataList.add(Integer.parseInt(TwoDigits3, 16));
            dataList.add(Integer.parseInt(TwoDigits4, 16));
        }

        //把slaveId，model，addr，num 放入集合，计算crc
        List<String> dates = new ArrayList<>();
        dates.add(String.format("%02X", slaveId));
        dates.add(String.format("%02X", model));

        //确定发送报文时第三字节是寄存器数量or起始地址
        switch (model) {
            case 06:
            case 16: {
                String add = String.format("%04X", addrOrNum);
                String adda = add.substring(0, 2);
                String addb = add.substring(2, 4);
                dates.add(adda);
                dates.add(addb);
                break;
            }
            case 03:
            case 04: {
                int i = addrOrNum * 2;
                String num1 = String.format("%02X", i);
                dates.add(num1);
                break;
            }
            default:
                log.error("发送报文时，解析区分0304/0616 出错，此时的数据:slaveId:{},model:{},addrOrNum:{},date:{}", slaveId, model, addrOrNum, date.toString());
        }

        for (int i = 0; i < dataList.size(); i++) {

            String value = String.format("%02X", dataList.get(i));
            dates.add(value);
        }

        byte[] crcByte = new byte[0];
        for (String date2 : dates) {
            int date10 = Integer.parseInt(date2, 16);
            // 扩展crc数组长度
            crcByte = Arrays.copyOf(crcByte, crcByte.length + 1);
            // 将date10添加到crc数组末尾
            crcByte[crcByte.length - 1] = (byte) date10;
        }
        String crc = Crc.Crc16(crcByte);

//        System.out.println("CRC校验值: " + crc);
        String firstTwoDigits = crc.substring(0, 2);
        String secondTwoDigits = crc.substring(2, 4);
        dates.add(firstTwoDigits);
        dates.add(secondTwoDigits);

        StringBuilder sb = new StringBuilder();
        for (String byteStr : dates) {
            sb.append(byteStr).append(" ");
        }
        String message = sb.toString().trim();
//        System.out.println("回复TX报文: " + message);
        String[] byteStrings = message.split(" ");
        // 创建一个与 byteStrings 长度相同的 byte 数组
        byte[] byteArray = new byte[byteStrings.length];

        // 将每个字符串解析为十六进制并放入 byte 数组
        for (int i = 0; i < byteStrings.length; i++) {
            byteArray[i] = (byte) Integer.parseInt(byteStrings[i], 16);
        }

        try {
            // 发送Modbus报文
            serialPort.writeBytes(byteArray);
        } catch (SerialPortException e) {
            throw new RuntimeException(e);
        }
    }
}
